/**
 * tigerrad
 * fall 2006
 */

#include "SDLWindow.h"

//////////////////////////////////////////////////

SDLWindow::SDLWindow(const Vec2s& size, GLuint depth, bool full, bool resizeable) 
		: _size(size), _depth(depth), _fullscreen(full), _resizeable(resizeable), _fps(true)
{
	const SDL_VideoInfo *videoInfo;
	
	// Standard SDL init w/ some OpenGL fun
	if (SDL_Init(SDL_INIT_VIDEO) < 0) {
		std::string err("Video initialization failed: ");
		err += SDL_GetError();
		throw err;
	}
	videoInfo = SDL_GetVideoInfo();
	if (!videoInfo) {
		std::string err("Video query failed: ");
		err += SDL_GetError();
		throw err;		
    }
	_videoFlags = SDL_OPENGL;
	_videoFlags |= SDL_GL_DOUBLEBUFFER;
	_videoFlags |= SDL_HWPALETTE;
	// TODO not resizeable
	//_videoFlags |= SDL_RESIZABLE;

	if (videoInfo->hw_available)
		_videoFlags |= SDL_HWSURFACE;
	else
		_videoFlags |= SDL_SWSURFACE;
	
	if (videoInfo->blit_hw)
		_videoFlags |= SDL_HWACCEL;
	
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

	_surface = SDL_SetVideoMode(_size[0], _size[1], _depth,
				_videoFlags);

	if (!_surface) {
		std::string err("Video mode set failed: ");
		err += SDL_GetError();
		throw err;				
	}

}

//////////////////////////////////////////////////

void SDLWindow::toggleFullscreen() 
{
	_fullscreen = !_fullscreen;
	SDL_WM_ToggleFullScreen(_surface);
}

//////////////////////////////////////////////////

void SDLWindow::mainLoop() 
{
    bool done = false;
	SDL_Event event;	
	unsigned int ticks, lastTicks = SDL_GetTicks();
	
	
	assert(_sim != 0);
	assert(_engine != 0);
	assert(_sim->getScene() != 0);
	_engine->init(_size);
	_engine->resize(_size);
	_engine->setScene(_sim->getScene());

	unsigned int frames(0), lastSec(0);

	while (!done) {
		while (SDL_PollEvent(&event)) {
			switch (event.type) {
				case SDL_VIDEORESIZE:
					if (!_resizeable) break;
					SDL_FreeSurface(_surface);
					_surface = SDL_SetVideoMode(event.resize.w,
						event.resize.h, SCREEN_BPP, _videoFlags);
					if (!_surface) {
						std::string err("Could not get a surface after resize: ");
						err += SDL_GetError();
						throw err;				
					}
					_size[0] = event.resize.w;
					_size[1] = event.resize.h;
					_engine->resize(_size);
					break;
				case SDL_KEYDOWN:
					_sim->handleKeyPress(&event.key.keysym);
					break;
				case SDL_KEYUP:
					_sim->handleKeyRelease(&event.key.keysym);
					break;
				case SDL_MOUSEMOTION:
					_sim->handleMouseMotion(&event.motion);
					break;
				case SDL_QUIT:
					done = true;
					break;
				default:
					break;
			}
		}
		if (!done) {
			done = _sim->finished();
			ticks = SDL_GetTicks();

			if (_fps && (ticks - lastSec >= 1000)) {
				// TODO not perfect...
				std::cerr << "FPS : " << frames/(float)(ticks-lastSec)*1000 << std::endl;
				frames = 0;
				lastSec = ticks;
			}

			_sim->step(ticks - lastTicks);
			ticks = lastTicks;
			_engine->render();
			SDL_GL_SwapBuffers();
			frames++;
		}
	}
}

